package com.mx.utils;

/**
 * DownloadUtils.java
 * Created at 2016-12-15
 * Created by asd
 * Copyright (C) 2016 SAIC VOLKSWAGEN, All rights reserved.
 */

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;

/**
 * <p>
 * ClassName: DownloadUtils
 * </p>
 * <p>
 * Description: 下载文件工具类
 * </p>
 * <p>
 * Author: zhangzhiyu
 * </p>
 * <p>
 * Date: 2016年12月15日
 * </p>
 */
public class DownloadUtils {

    /**
     * <p>
     * Description: 下载文件
     * </p>
     * 
     * @param request 请求参数
     * @param response 响应参数
     * @param downloadFile 需下载的文件
     * @param fileName 文件名称
     * @throws IOException 异常
     */
    public static void download(HttpServletRequest request, HttpServletResponse response, File downloadFile,
        String fileName) throws IOException {

        // 记录文件大小
        long fileLength = downloadFile.length();

        // 记录已下载文件大小
        long pastLength = 0;

        // 客户端请求的字节总量
        long contentLength = 0;

        // 负责读取数据
        RandomAccessFile raf = null;

        // 缓冲
        BufferedOutputStream out = null;

        // 暂存容器
        byte[] b = new byte[com.mx.utils.Constants.IO_BUFFERED];

        String range = "Range";

        try {

            // 判断是否包含断点请求
            if (request.getHeader(range) != null) {

                //// 获取range,客户端请求的是 969998336 之后的字节 ,设置响应类型
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                String rangeBytes = "";
                rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");
                rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));
                pastLength = Long.parseLong(rangeBytes.trim());
                contentLength = fileLength - pastLength;
            } else { // 从开始进行下载
                contentLength = fileLength; // 客户端要求全文下载
            }

            if (pastLength != 0) {
                // 不是从最开始下载,
                // 响应的格式是: Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
                String contentRange = new StringBuffer("bytes ").append(Long.toString(pastLength)).append("-")
                    .append(Long.toString(fileLength - 1)).append("/").append(Long.toString(fileLength)).toString();
                response.setHeader("Content-Range", contentRange);
            }

            // 设置相应参数
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Accept-Ranges", "bytes"); // 如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置;响应的格式是:HTTP/1.1 200 OK
            response.setHeader("Content-Length", String.valueOf(contentLength));
            response.setHeader("Content-disposition", "attachment; filename="
                + new String(fileName.getBytes(), "iso8859-1"));

            out = new BufferedOutputStream(response.getOutputStream());
            raf = new RandomAccessFile(downloadFile, "r");

            raf.seek(pastLength); // 形如 bytes=969998336- 的客户端请求，跳过 969998336 个字节
            int n = 0;
            while ((n = raf.read(b, 0, com.mx.utils.Constants.IO_BUFFERED)) != -1) {
                out.write(b, 0, n);
            }

        } catch (IOException e) {
            throw new IOException(e);
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if (raf != null) {
                raf.close();
            }
        }
    }

}
